#!/usr/bin/env node

# Determine data file name and database name from argument list. Data file name
# is mandatory; database name is optional, and if given, objects found in the
# JSON data file will be saved in the database, otherwise JSON text is written
# to stdout.
#
# Note: we must process donors first, then donations
#
Usage = 'Usage: node export.js dataName [http://serverName:portNum/dbName]'
dataName = dbName = ''
serverName = '192.168.2.14'
portNum = '5984'
process.argv.slice(2).forEach (v, n) ->
	switch n
		when 0 then dataName = v
		when 1 then dbName = v
unless dataName?
	console.log Usage
	process.exit() 
if x = dbName.match /^http:\/\/(\S+?):(\d+?)\/(\S+?)$/
	serverName = x[1] if x[1]
	portNum = x[2] if x[2]
	dbName = x[3] if x[3]

# Read and parse JSON text in data file into document objects
console.log "Parsing #{dataName} file into documents..."
fs = require 'fs'
docs = JSON.parse fs.readFileSync dataName, 'utf8'

# We need to transform incoming documents to outgoing documents.
# 1. Remove properties with null values
# 2. Make better distinction between donations and donors
# 3. Similarly, between group donors and individual donors
# 4. Normalize boolean properties into 'true' and 'false' values
# 5. Rename _id property of donations
console.log "Transforming document structure..."
re_donor_name = /^(\S+(?:\s+\S+)*)(?:\s+(\S+))$/
for doc in docs
	(delete doc[n] unless v?) for n, v of doc
	if doc.org?
		doc['type'] = 'donor'

		#console.log doc._id
		switch doc.org
			# In donor documents for an organization,
			when '1', '-1'
				doc.org = true
				# last_name stores org name
				if (ln = doc.last_name)?
					doc['org_name'] = ln
					delete doc.last_name
				# first_name stores contact name
				if (x = doc.first_name)?
					if (x = x.match re_donor_name)?
						doc.first_name = x[1] if x[1]
						doc['last_name'] = x[2] if x[2]
				# tel_home stores contact tel. number
				if (th = doc.tel_home)?
					doc['tel_contact'] = th
					delete doc.tel_home
			else doc.org = false

	else
		doc['type'] = 'donation'
		# Normalize boolean properties of donation documents
		switch doc.cash
			when '1', '-1' then doc.cash = true
			else doc.cash = false
		switch doc.receipt_given
			when '1', '-1' then doc.receipt_given = true
			else doc.receipt_given = false
		doc['old_id'] = doc._id
		delete doc._id

# Unless a database name is given on command line, the updated document objects
# are written in JSON format to stdout.
unless dbName
	u = require 'util'
	console.log u.inspect docs
	process.exit()

# Define a callback to handle erroneous or successful document saves
save_cb = (err, resp) ->
	if err
		console.error "#{err.error} #{err.reason}"
	else
		console.log JSON.stringify resp

# Try to connect to our database server
cradle = require 'cradle'
c = new cradle.Connection "http://#{serverName}", portNum,
	cache: true
	raw: false
db = c.database dbName

# If our database exists save all documents, otherwise create the database
db.exists (err, exists) ->
	if err
		console.error "#{dbName} error", err
	else if exists
		console.log "Saving #{dataName} in #{dbName}"
		if docs[0].type is 'donor'
			(db.save doc._id, doc, save_cb) for doc in docs
		else
			db.save docs, save_cb
	else
		console.log "Creating #{dbName}"
		db.create()
